import 'dart:ui' as ui;

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

import '../common/coordinate.dart';

class Paper extends StatefulWidget {
  const Paper({super.key});

  @override
  State<Paper> createState() => _PaperState();
}

class _PaperState extends State<Paper> {
  ui.Image? _image;

  @override
  void initState() {
    super.initState();
    _loadImage();
  }

  void _loadImage() async {
    _image = await loadImageFromAssets('assets/images/ic_head.png');
    setState(() {});
  }

  Future<ui.Image>? loadImageFromAssets(String path) async {
    ByteData data = await rootBundle.load(path);
    return decodeImageFromList(data.buffer.asUint8List());
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.white,
      child: CustomPaint(
        painter: PaperPainter(_image),
      ),
    );
  }
}

class PaperPainter extends CustomPainter {
  final ui.Image? image;

  PaperPainter(this.image);

  static const double step = 15;
  final CoordinateByPath coordinate = CoordinateByPath(step: step);

  @override
  void paint(Canvas canvas, Size size) {
    coordinate.paint(canvas, size);

    //testDrawColorList(canvas);
    testBlendMode(canvas);
  }

  /// 绘制颜色阵列
  // 下面是一个红色透明度依次降低的色块。是一个0xffff000~ox00ff0000共 256 个颜色的列表绘制而成图案。
  // 在这里想要介绍一下如何通过一维数组取商和取余绘制出类似二维(有行列)的效果。
  void testDrawColorList(Canvas canvas, Size size) {
    // 原点坐标移动到屏幕中心
    canvas.translate(size.width / 2, size.height / 2);
    // 颜色列表 256 个元素
    List<Color> colors = List<Color>.generate(
        256, (index) => Color.fromARGB(255 - index, 255, 0, 0));
    Paint paint = Paint();

    canvas.save();
    // 遍历列表绘制色块
    canvas.translate(-step * 8, -step * 8);
    colors.asMap().forEach((i, color) {
      int line = (i % 16); // 行
      int row = i ~/ 16; // 列
      var topLeft = Offset(step * line, step * row);
      var rect = Rect.fromPoints(topLeft, topLeft.translate(step, step));
      canvas.drawRect(rect, paint..color = color);
    });
    canvas.restore();
  }

  /// 混合模式
  // 颜色混合模式，即 在画布上绘制时使用的算法。当在画布上绘制形状或图片时，BlendMode决定混合像素时使用的算法。
  // 既然是混合，那么肯定要两个东西混在一起，这就是 src 和 dst 。src 顾名思义是源，dst 是目标。
  // 一般 dst 会被认为是背景，src 被认为是 正在绘制的图像。 下面示例代码为红色叠合头像的效果。
  void testBlendMode(Canvas canvas) {
    if (image == null) return;

    Paint srcPaint = Paint();
    Paint dstPaint = Paint();

    canvas.translate(30, 30);
    BlendMode.values.asMap().forEach((i, value) {
      int line = i ~/ 10;
      int row = i % 10;
      canvas.save();

      canvas.translate(70.0 * row, 120.0 * line);
      canvas.drawImageRect(
          image!,
          Rect.fromPoints(
              Offset.zero, Offset(image!.width * 1, image!.height * 1)),
          Rect.fromCenter(center: Offset.zero, width: 50, height: 50),
          dstPaint);

      srcPaint
        ..color = const Color(0xffff0000)
        ..blendMode = value;
      canvas.drawRect(
          Rect.fromPoints(Offset.zero, const Offset(40, 40)), srcPaint);

      _drawText(canvas, value.toString().split(".")[1],
          offset: const Offset(-20, 50));
      canvas.restore();
    });
  }

  void _drawText(Canvas canvas, String str,
      {Offset offset = Offset.zero, Color color = Colors.black}) {
    var builder = ui.ParagraphBuilder(ui.ParagraphStyle(
        textAlign: TextAlign.left,
        fontSize: 11,
        textDirection: TextDirection.ltr,
        maxLines: 1))
      ..pushStyle(
          ui.TextStyle(color: color, textBaseline: ui.TextBaseline.alphabetic))
      ..addText(str);

    canvas.drawParagraph(
        builder.build()
          ..layout(ui.ParagraphConstraints(width: 11.0 * str.length)),
        offset);
  }

  @override
  bool shouldRepaint(covariant PaperPainter oldDelegate) => false;
}
